package com.github.jspxnet.worktask.dao.impl;

import com.github.jspxnet.enums.RecycleEnumType;
import com.github.jspxnet.json.JSONObject;
import com.github.jspxnet.sioc.annotation.Bean;
import com.github.jspxnet.sober.Criteria;
import com.github.jspxnet.sober.annotation.SqlMap;
import com.github.jspxnet.sober.criteria.expression.Expression;
import com.github.jspxnet.sober.criteria.projection.Projections;
import com.github.jspxnet.sober.enums.QueryModelEnumType;
import com.github.jspxnet.sober.jdbc.JdbcOperations;
import com.github.jspxnet.sober.ssql.SSqlExpression;
import com.github.jspxnet.utils.BeanUtil;
import com.github.jspxnet.utils.ObjectUtil;
import com.github.jspxnet.utils.StringUtil;
import com.github.jspxnet.worktask.dao.RuntimeServiceDAO;
import com.github.jspxnet.worktask.env.JWorkTask;
import com.github.jspxnet.worktask.model.enums.FlowNodeEnumType;
import com.github.jspxnet.worktask.table.ConfFlowNode;
import com.github.jspxnet.worktask.table.WorkTask;
import com.github.jspxnet.worktask.table.WorkTaskVariable;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Bean(namespace = JWorkTask.namespace)
public class RuntimeServiceDAOImpl extends JdbcOperations implements RuntimeServiceDAO {

    public int currentVersion(String flowNo, String namespace, String documentNo)
    {
        String sql = "SELECT max(version) as version FROM " + getTableName(WorkTask.class) + " WHERE namespace=? AND flowNo=? AND documentNo=?";
        return ObjectUtil.toInt(super.getUniqueResult(sql,new Object[]{namespace,flowNo,documentNo}));
    }
    /**
     * @param flowNo     流程编号
     * @param namespace  命名空间
     * @param documentNo 文档号
     * @return 返回当前没有完成的当前任务id列表, 如果有分子这里就会出现多个, 形成列表
     */
    @Override
    public List<WorkTask> getWorkTaskList(String flowNo, String namespace, String documentNo) {

        int version = currentVersion( flowNo,  namespace,  documentNo);
        Criteria criteria = createCriteria(WorkTask.class).add(Expression.eq("namespace", namespace))
                .add(Expression.eq("version", version));
        criteria = criteria.add(Expression.eq("flowNo", flowNo));
        criteria = criteria.add(Expression.eq("documentNo", documentNo));
        criteria = criteria.add(Expression.eq("recycleType", RecycleEnumType.NO_RECYCLE.getValue()));
        criteria = criteria.add(Expression.ne("flowNodeType", FlowNodeEnumType.END.getValue()));

        return SSqlExpression.getSortOrder(criteria, "createDate:D").setCurrentPage(1).setTotalCount(10000).list(false);
    }
    /**
     * @param flowNo    流程编号
     * @param namespace 命名空间
     * @return 得到流程的所有当前需要执行的节点
     */
    @Override
    public List<WorkTask> getWorkTaskList(String flowNo, String namespace) {
        Criteria criteria = createCriteria(WorkTask.class).add(Expression.eq("namespace", namespace));
        criteria = criteria.add(Expression.eq("flowNo", flowNo));
        criteria = criteria.add(Expression.ne("flowNodeType", FlowNodeEnumType.END.getValue()));
        return SSqlExpression.getSortOrder(criteria, "createDate:D").setCurrentPage(1).setTotalCount(10000).list(false);
    }

    /**
     *
     * @param flowNo 流程编号
     * @param namespace 命名空间
     * @param currentPage 页数
     * @param count 总数
     * @return 得到流程的所有当前需要执行的节点
     */
    @Override
    public List<String> getDocumentList(String flowNo, String namespace, int currentPage, int count) {
        Criteria criteria = createCriteria(WorkTask.class).add(Expression.eq("namespace", namespace));
        criteria = criteria.add(Expression.eq("flowNo", flowNo));
        criteria = criteria.add(Expression.eq("recycleType", RecycleEnumType.NO_RECYCLE.getValue()));
        criteria = criteria.add(Expression.ne("flowNodeType", FlowNodeEnumType.END.getValue()));
        List<WorkTask> list = SSqlExpression.getSortOrder(criteria, "createDate:A").setCurrentPage(currentPage).setTotalCount(count).list(false);
        List<String> result = BeanUtil.copyFieldList(list, "documentNo");
        return result.stream().distinct().collect(Collectors.toList());
    }

    /**
     * @param flowNo     流程
     * @param namespace  命名空间
     * @param documentNo 文档
     * @param nodeId     节点
     * @return 得到完整的当前任务
     */
    @Override
    public WorkTask getWorkTask(String flowNo, String namespace, String documentNo, String nodeId) {
        int version = currentVersion( flowNo,  namespace,  documentNo);
        Criteria criteria = createCriteria(WorkTask.class).add(Expression.eq("namespace", namespace))
                .add(Expression.eq("version", version));
        criteria = criteria.add(Expression.eq("flowNo", flowNo));
        criteria = criteria.add(Expression.eq("documentNo", documentNo));
        criteria = criteria.add(Expression.eq("nodeId", nodeId));
        return SSqlExpression.getSortOrder(criteria, "version:D").objectUniqueResult(true);
    }

    /**
     *
     * @param flowNo  流程编号
     * @param namespace 命名空间
     * @param documentNo 文档id
     * @return 是否可以启动,没有启动说明流程里边有
     */
    @Override
    public boolean canStart(String flowNo, String namespace, String documentNo)
    {
        int version = currentVersion( flowNo,  namespace,  documentNo);
        Criteria criteria = createCriteria(WorkTask.class).add(Expression.eq("namespace", namespace))
                .add(Expression.eq("version", version));
        criteria = criteria.add(Expression.eq("flowNo", flowNo));
        criteria = criteria.add(Expression.eq("documentNo", documentNo));
        criteria = criteria.add(Expression.ne("flowNodeType",FlowNodeEnumType.END.getValue()));
        return criteria.setProjection(Projections.rowCount()).intUniqueResult()<=0;
    }


    /**
     *
     * @param valueMap 变量
     * @return 是否有结束
     */
    @SqlMap(mode = QueryModelEnumType.SINGLE)
    @Override
    public int isFlowFinished(Map<String, Object> valueMap)
    {
        valueMap.put("workTaskTable",getTableName(WorkTask.class));
        valueMap.put("confFlowNodeTable",getTableName(ConfFlowNode.class));
        return 0;
    }

    /**
     * @param flowNo     流程编号
     * @param namespace  命名空间
     * @param documentNo 文档id
     * @return 删除所有流程节点
     */
    @Override
    public int deleteWorkTask(String flowNo, String namespace, String documentNo) {
        int version = currentVersion( flowNo,  namespace,  documentNo);
        Criteria criteria = createCriteria(WorkTask.class).add(Expression.eq("namespace", namespace))
                .add(Expression.eq("version", version));
        criteria = criteria.add(Expression.eq("flowNo", flowNo));
        criteria = criteria.add(Expression.eq("documentNo", documentNo));
        return criteria.delete(true);
    }

    /**
     *
     * @param flowNo  流程编号
     * @param namespace   命名空间
     * @param documentNo  文档id
     * @param userId  用户ID
     * @return  删除所有流程节点
     */
    @Override
    public int isAudited(String flowNo, String namespace, String documentNo,String userId) {
        int version = currentVersion( flowNo,  namespace,  documentNo);
        Criteria criteria = createCriteria(WorkTask.class).add(Expression.eq("namespace", namespace))
                .add(Expression.eq("version", version));
        criteria = criteria.add(Expression.eq("flowNo", flowNo));
        criteria = criteria.add(Expression.eq("documentNo", documentNo));
        criteria = criteria.add(Expression.like("users", "["+userId + ":%"));
        return criteria.setProjection(Projections.rowCount()).intUniqueResult();
    }

    /**
     *
     * @param flowNo  流程编号
     * @param namespace 命名空间
     * @param documentNo  文档id
     * @param joinNodeId  有join节点的节点
     * @return 返回已经执行了的join节点
     */
    @Override
    public List<WorkTask> getJoinExeNodeList(String flowNo, String namespace, String documentNo, List<String> joinNodeId)
    {
        int version = currentVersion( flowNo,  namespace,  documentNo);
        Criteria criteria = createCriteria(WorkTask.class).add(Expression.eq("namespace", namespace))
                .add(Expression.eq("version", version));
        criteria = criteria.add(Expression.eq("flowNo", flowNo));
        criteria = criteria.add(Expression.eq("documentNo", documentNo));
        criteria = criteria.add(Expression.in("nodeId", joinNodeId));
        criteria = criteria.add(Expression.eq("flowNodeType",FlowNodeEnumType.END.getValue()));
        return criteria.setCurrentPage(1).setTotalCount(1000).list(false);
    }


    /**
     * 更新分支节点合并成功
     * @param flowNo  流程编号
     * @param namespace  命名空间
     * @param nodeId  文档id
     * @param documentNo 文档ID
     * @return 更新状态
     * @throws Exception  异常
     */
    @Override
    public int updateJoinFinished(String flowNo, String namespace, String nodeId,String documentNo) throws Exception {
        int version = currentVersion( flowNo,  namespace,  documentNo);
        Criteria criteria = createCriteria(WorkTask.class).add(Expression.eq("namespace", namespace))
                .add(Expression.eq("version", version));
        criteria = criteria.add(Expression.eq("flowNo", flowNo));
        criteria = criteria.add(Expression.eq("nodeId", nodeId));
        criteria = criteria.add(Expression.eq("documentNo", documentNo));
        List<WorkTask> list = criteria.setCurrentPage(1).setTotalCount(10000).list(false);
        if (ObjectUtil.isEmpty(list))
        {
            return -1;
        }
        //这里需要做合并处理
        WorkTask oneWorkTask = list.get(0);
        StringBuilder users = new StringBuilder();
        for (WorkTask workTask : list) {
            users.append(workTask.getUsers()).append(StringUtil.SEMICOLON);
        }
        if (users.toString().endsWith(StringUtil.SEMICOLON))
        {
            users.setLength(users.length()-1);
        }
        oneWorkTask.setUsers(users.toString());
        oneWorkTask.setFlowNodeType(FlowNodeEnumType.END.getValue());
        oneWorkTask.setCreateDate(new Date());
        for (int i=1;i<list.size();i++)
        {
            super.delete(list.get(i));
        }
        return super.update(oneWorkTask);
    }

    /**
     * @param varNo 变量编号
     * @return 返回变量配置
     */
    @Override
    public WorkTaskVariable getWorkTaskVariable(String varNo) {
        return super.load(WorkTaskVariable.class, varNo);
    }

    /**
     *
     * @param varNo 变量编号
     * @param json  变量
     * @return 是否保存成功
     */
    @Override
    public int putWorkTaskVariable(String varNo, JSONObject json) {
        try {
            WorkTaskVariable workTaskVariable = super.load(WorkTaskVariable.class, varNo);
            if (StringUtil.isNull(workTaskVariable.getId())) {
                workTaskVariable.setId(varNo);
                workTaskVariable.setValueMap(json.toString());
                return super.save(workTaskVariable);
            }
            String valueMap = workTaskVariable.getValueMap();
            JSONObject oldJson = new JSONObject(valueMap);
            oldJson.putAll(json);
            workTaskVariable.setValueMap(new JSONObject(oldJson).toString());
            return super.update(workTaskVariable);
        } catch (Exception e) {
            e.printStackTrace();
            return -2;
        }

    }
}
